package com.ale.oxetool.service;

import com.ale.oxetool.exceptions.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;

/**
 * Created by wgs on 4/19/2016.
 */
@Component
public class RemoteCommandServicePool {
    @Value("${oxeserver.pool.size}")
    private int size;

    private BlockingQueue<RemoteCommandService> pool1;
    private BlockingQueue<RemoteCommandService> pool2;

    @Autowired
    private OXEServerSettings oxe1Settings;
    @Autowired
    private OXEServerSettings oxe2Settings;

    @Value("${telnet.read.timeout}")
    private long readTimeOut;

    @Value("${config.test.debug:false}")
    private boolean debug;

    private static Logger log = LoggerFactory.getLogger(RemoteCommandServicePool.class);

    OXEServerSettings getOXESettings(int index) {
        if (1 == index) {
            return oxe1Settings;
        }
        if (2 == index) {
            return oxe2Settings;
        }
        return null;
    }

    @PostConstruct
    public void init() throws IOException, BusinessException {
        if (debug) {
            return;
        }
        this.initPool();
    }

    private BlockingQueue<RemoteCommandService> initPool(int index) throws IOException, BusinessException {
        BlockingQueue<RemoteCommandService> pool = new LinkedBlockingDeque<>();
        OXEServerSettings settings = getOXESettings(index);
        if (null == settings) {
            throw new BusinessException("Invalid settings");
        }
        for (int i = 0; i < size; ++i) {
            RemoteCommandService rce = settings.isSSH() ? new SSHOXEConnection(settings) : new TelnetOXEConnection(settings);
            if (rce instanceof TelnetOXEConnection) {
                ((TelnetOXEConnection) rce).setReadTimeout(readTimeOut);
            }
            rce.setPool(pool);
            pool.add(rce);
            log.info("Create connection[{}] to {} done", i, settings);
        }
        return pool;
    }

    private void initPool() throws IOException, BusinessException {
        log.info("Initialize connection pool. This will take few seconds, please wait...");
        pool1 = initPool(1);
        pool2 = initPool(2);
    }

    RemoteCommandService getRCS1() throws InterruptedException {
//        log.debug("Current rest connection in pool1: {}", pool1.size());
        return pool1.take();
    }

    RemoteCommandService getRCS2() throws InterruptedException {
//        log.debug("Current rest connection in pool2: {}", pool2.size());
        return pool2.take();
    }

    @PreDestroy
    public void releasePool() throws IOException {
        for (RemoteCommandService rce : pool1) {
            rce.disconnect();
        }

        for (RemoteCommandService rce : pool2) {
            rce.disconnect();
        }
    }
}
